package com.hippo.provider.task;

import com.hippo.core.config.ScheduleConfig;
import com.hippo.core.pojo.entity.SysNotice;
import com.hippo.core.pojo.entity.SysTask;
import com.hippo.core.pojo.task.CustomizeTask;
import com.hippo.core.pojo.vo.result.BaseResult;
import com.hippo.database.mapper.SysNoticeMapper;
import com.hippo.database.mapper.SysTaskMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronExpression;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ScheduledFuture;

/**
 * @ClassName TeskSchedulerTest
 * @Description TODO 定时任务测试
 * @Author tangxl
 * @create 2023-04-28 10:20
 **/
@Slf4j
@Component
@RequiredArgsConstructor // 生成一个包含常量，和标识了NotNull的变量的构造方法
public class TaskSchedulerTest {

    /**
     * 线程池任务调度器
     */
    private final ThreadPoolTaskScheduler threadPoolTaskScheduler;
    private final SysNoticeMapper sysNoticeMapper;
    private final SysTaskMapper sysTaskMapper;

    /**
     * 启动定时任务
     */
    public BaseResult startCron(String taskCode, String cron) {
        // 校验任务是否存在
        SysTask sysTask = sysTaskMapper.selectOneByCode(taskCode);
        if (ObjectUtils.isEmpty(sysTask)) {
            return BaseResult.fail("任务不存在！");
        }
        // 校验cron表达式
        if(StringUtils.isEmpty(cron)){
            cron = sysTask.getCron();
        }else if (StringUtils.isNotBlank(taskCode) && !CronExpression.isValidExpression(cron)) {
            return BaseResult.fail("cron表达式有误，不能被解析！");
        }
        getTasks().forEach(task -> {
            if(task.getCode().equals(sysTask.getCode())){
                // 启动定时任务
                ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(task, new CronTrigger(task.getCron()));
                // 将 scheduledFuture 保存下来用于停止任务使用
                ScheduleConfig.cache.put(task.getCode(), scheduledFuture);
            }
        });
        return BaseResult.ok("启动成功！",taskCode);
    }

    /**
     * 根据任务ID停止定时任务
     */
    public BaseResult stopCron(String taskCode) {
        if (ScheduleConfig.cache.isEmpty()) {
            return BaseResult.fail("当前无任务在执行");
        }
        if (ScheduleConfig.cache.get(taskCode) == null) {
            return BaseResult.fail("无法停止，任务不存在");
        }
        ScheduledFuture scheduledFuture = ScheduleConfig.cache.get(taskCode);

        if (scheduledFuture != null) {
            scheduledFuture.cancel(true);   // 这里需要使用指定的 scheduledFuture 来停止当前的线程
            ScheduleConfig.cache.remove(taskCode);        // 移除缓存
        }
        return BaseResult.ok("停止成功！",taskCode);
    }

    /**
     * 停止所有定时任务
     */
    public BaseResult stopAllCron() {
        if (ScheduleConfig.cache.isEmpty()) {
            return BaseResult.fail("当前无任务在执行");
        }
        List<String> taskCodes = new ArrayList<>();
        ScheduleConfig.cache.forEach(
                (k,v) -> {
                    v.cancel(true);
                    taskCodes.add(k);
                }
        );
        ScheduleConfig.cache.clear();
        return BaseResult.ok("停止成功！",taskCodes);
    }

    private List<CustomizeTask> getTasks(){
        return Arrays.asList(new AddSysNoticeTask("task_001","任务一", "0/2 * * * * ?"),
                new CustomizeTask("task_002","任务二", "0/1 * * * * ?"));
    }

    public BaseResult startAllCron() {
        List<String> taskCodes = new ArrayList<>();
        List<SysTask> sysTasks = sysTaskMapper.selectAll();
        getTasks().forEach(task -> {
            sysTasks.stream().forEach(sysTask -> {
                if(task.getCode().equals(sysTask.getCode())){
                    // 启动定时任务
                    ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(task, new CronTrigger(task.getCron()));
                    // 将 scheduledFuture 保存下来用于停止任务使用
                    ScheduleConfig.cache.put(task.getCode(), scheduledFuture);
                    taskCodes.add(task.getCode());
                }
            });
        });
        return BaseResult.ok("启动所有任务成功！",taskCodes);
    }

    public BaseResult showAllTask() {
        List<String> taskCodes = new ArrayList<>();
        log.info("当前任务数量：{}",ScheduleConfig.cache.size());
        ScheduleConfig.cache.forEach((k,v)->{
            log.info("key:{},value:{}",k,v);
            taskCodes.add(k);
        });
        return BaseResult.ok(taskCodes);
    }

    public class AddSysNoticeTask extends CustomizeTask{

        public AddSysNoticeTask(String code,String name, String cron) {
            super(code,name, cron);
        }

        @Override
        public void run() {
            super.run();
            SysNotice sysNotice = new SysNotice();
            sysNotice.setTitle("执行定时任务");
            sysNotice.setNotice("任务名称"+this.getName()+";执行时间：" + LocalDateTime.now());
            sysNotice.setCutoffTime(LocalDateTime.now().plusDays(7));
            sysNotice.setCreateTime(LocalDateTime.now());
            sysNoticeMapper.insert(sysNotice);
        }
    }


}
